﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Company.Shell.Controls
{
    public class Gauge : Control
    {
        RotateTransform? rotateTransform;//旋转变换
        Grid? container;//网格容器
        
        // 添加Value依赖属性
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(Gauge), 
                new PropertyMetadata(50.0, new PropertyChangedCallback(OnValueChanged), CoerceValue));
        
        // 添加Maximum依赖属性
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(Gauge), 
                new PropertyMetadata(100.0, new PropertyChangedCallback(OnRangeChanged), CoerceMaximum));
        
        // 添加Minimum依赖属性
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(Gauge), 
                new PropertyMetadata(0.0, new PropertyChangedCallback(OnRangeChanged), CoerceMinimum));
        
        // 添加Title依赖属性
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(Gauge), 
                new PropertyMetadata("标题"));
        
        // 添加PointerColor依赖属性
        public static readonly DependencyProperty PointerColorProperty =
            DependencyProperty.Register("PointerColor", typeof(Brush), typeof(Gauge), 
                new PropertyMetadata(Brushes.DodgerBlue));
        
        // Value属性
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
        
        // Maximum属性
        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }
        
        // Minimum属性
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }
        
        // Title属性
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
        
        // PointerColor属性
        public Brush PointerColor
        {
            get { return (Brush)GetValue(PointerColorProperty); }
            set { SetValue(PointerColorProperty, value); }
        }
        
        // 值变化回调
        private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Gauge gauge = (Gauge)d;
            gauge.UpdatePointer();
        }
        
        // 范围变化回调
        private static void OnRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Gauge gauge = (Gauge)d;
            gauge.CoerceValue(ValueProperty);
            gauge.UpdatePointer();
            // 重新初始化刻度，因为范围可能改变了
            if (gauge.container != null)
            {
                gauge.container.Children.Clear();
                gauge.Initialize();
            }
        }
        
        // 强制Value在有效范围内
        private static object CoerceValue(DependencyObject d, object value)
        {
            Gauge gauge = (Gauge)d;
            double newValue = (double)value;
            
            // 确保Value在Minimum和Maximum之间
            if (newValue < gauge.Minimum)
                return gauge.Minimum;
            if (newValue > gauge.Maximum)
                return gauge.Maximum;
                
            return newValue;
        }
        
        // 强制Maximum不小于Minimum
        private static object CoerceMaximum(DependencyObject d, object value)
        {
            Gauge gauge = (Gauge)d;
            double newMaximum = (double)value;
            
            if (newMaximum < gauge.Minimum)
                return gauge.Minimum;
                
            return newMaximum;
        }
        
        // 强制Minimum不大于Maximum
        private static object CoerceMinimum(DependencyObject d, object value)
        {
            Gauge gauge = (Gauge)d;
            double newMinimum = (double)value;
            
            if (newMinimum > gauge.Maximum)
                return gauge.Maximum;
                
            return newMinimum;
        }
        
        // 更新指针位置
        private void UpdatePointer()
        {
            if (rotateTransform != null)
            {
                // 根据当前值计算指针角度（从-140度到+140度，对应Minimum-Maximum的值）
                double range = Maximum - Minimum;
                double normalizedValue = range > 0 ? (Value - Minimum) / range : 0;
                double angle = -140 + (normalizedValue * 280);
                rotateTransform.Angle = angle;
            }
        }

        public Gauge()
        {
            Width = 200;
            Height = 200;
        }
        
        static Gauge()//静态构造函数
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Gauge), new FrameworkPropertyMetadata(typeof(Gauge)));//重写默认样式
        }

        public override void OnApplyTemplate()//应用模板时调用
        {
            base.OnApplyTemplate();
            rotateTransform = GetTemplateChild("PointRotate") as RotateTransform;//获取旋转变换
            container = GetTemplateChild("container") as Grid;//获取网格容器
            if (rotateTransform != null && container != null)
            {
                Initialize();
                UpdatePointer(); // 初始化指针位置
            }
        }

        private void Initialize()
        {
            double angle = -140;//计算旋转角度
            double total = Math.Abs(angle) * 2;//总角度
            double bigStep = total / 10;//大刻度步长
            double smallStep = bigStep / 10;//小刻度步长

            // 创建Canvas来放置数字标签
            Canvas numbersCanvas = new Canvas
            {
                HorizontalAlignment = HorizontalAlignment.Stretch,
                VerticalAlignment = VerticalAlignment.Stretch
            };
            container.Children.Add(numbersCanvas);

            //画刻度线
            for (int i = 0; i <= 10; i++)
            {
                Line line = new()
                {
                    X1 = 0,
                    Y1 = 0,
                    X2 = 0,
                    Y2 = 12,
                    Stroke = Brushes.White,
                    StrokeThickness = 2,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    RenderTransformOrigin = new Point(0.5, 0.5),
                    RenderTransform = new RotateTransform() { Angle = angle + i * bigStep }//旋转刻度线
                };
                container.Children.Add(line);
                
                // 添加刻度数字 - 根据实际的最小值和最大值计算
                double range = Maximum - Minimum;
                double stepValue = range / 10;
                double currentValue = Minimum + (i * stepValue);
                
                TextBlock textBlock = new()
                {
                    Text = currentValue.ToString("0"), // 根据实际范围显示数字
                    Foreground = Brushes.White,
                    FontSize = 12,
                    HorizontalAlignment = HorizontalAlignment.Center,//水平居中
                    RenderTransformOrigin = new Point(0.5, 0.5),//设置旋转中心
                    Margin = new Thickness(10), // 调整数字位置
                    RenderTransform = new RotateTransform() { Angle = angle + i * bigStep }//旋转数字
                };
                container.Children.Add(textBlock);

                //画小刻度线
                if (i < 10)
                {
                    for (int j = 1; j < 10; j++)
                    {
                        Line smallLine = new()
                        {
                            X1 = 0,
                            Y1 = 0,
                            X2 = 0,
                            Y2 = 6,
                            Stroke = Brushes.White,
                            StrokeThickness = 1,
                            HorizontalAlignment = HorizontalAlignment.Center,
                            RenderTransformOrigin = new Point(0.5, 0.5),
                            RenderTransform = new RotateTransform() { Angle = angle + i * bigStep + j * smallStep }//旋转小刻度线
                        };
                        container.Children.Add(smallLine);
                    }
                }
            }
        }
    }
}
